import { BaseRenderer } from "./base_renderer.mjs";

/**
 * 基本输入类型渲染器
 * 处理文本、数字、布尔等基本类型的渲染
 */
export class InputRenderers extends BaseRenderer {
  /**
   * 创建文本输入框
   * @param {Object} schema - Schema定义
   * @param {*} data - 数据值
   * @param {Function} updateData - 数据更新函数
   * @returns {HTMLElement} 输入元素
   */
  static createTextInput(schema, data, updateData) {
    const input = document.createElement("input");
    input.type = "text";
    input.value = data || "";
    input.name = schema.path || schema.name;

    // 添加必填验证 - 优先使用thin.required
    const isRequired =
      schema.thin?.required !== undefined
        ? schema.thin.required
        : schema.parent &&
          schema.parent.required &&
          schema.parent.required.includes(schema.name);
    if (isRequired) {
      input.required = true;
      input.setAttribute("aria-required", "true");
    }

    // 添加长度验证
    if (schema.minLength !== undefined) {
      input.minLength = schema.minLength;
    }
    if (schema.maxLength !== undefined) {
      input.maxLength = schema.maxLength;
    }

    // 添加正则验证
    if (schema.pattern) {
      input.pattern = schema.pattern;
    }

    input.onchange = (e) => {
      const value = e.target.value;
      if (input.checkValidity()) {
        input.classList.remove("invalid");
        updateData(value);
      } else {
        input.classList.add("invalid");
      }
    };

    return input;
  }

  /**
   * 创建数字输入框
   * @param {Object} schema - Schema定义
   * @param {*} data - 数据值
   * @param {Function} updateData - 数据更新函数
   * @returns {HTMLElement} 输入元素
   */
  static createNumberInput(schema, data, updateData) {
    const input = document.createElement("input");
    input.type = "number";
    input.name = schema.path || schema.name;

    if (schema.type === "integer") {
      input.step = "1";
    } else {
      input.step = "any";
    }

    input.value = data || 0;

    // 添加必填验证 - 优先使用thin.required
    const isRequired =
      schema.thin?.required !== undefined
        ? schema.thin.required
        : schema.parent &&
          schema.parent.required &&
          schema.parent.required.includes(schema.name);
    if (isRequired) {
      input.required = true;
      input.setAttribute("aria-required", "true");
    }

    if (schema.minimum !== undefined) input.min = schema.minimum;
    if (schema.maximum !== undefined) input.max = schema.maximum;

    input.onchange = (e) => {
      if (input.checkValidity()) {
        input.classList.remove("invalid");
        updateData(Number(e.target.value));
      } else {
        input.classList.add("invalid");
      }
    };

    return input;
  }

  /**
   * 创建布尔值复选框
   * @param {Object} schema - Schema定义
   * @param {*} data - 数据值
   * @param {Function} updateData - 数据更新函数
   * @returns {HTMLElement} 输入元素
   */
  static createBooleanInput(schema, data, updateData) {
    const wrapper = document.createElement("div");
    wrapper.style.display = "inline-block";

    const checkbox = document.createElement("input");
    checkbox.type = "checkbox";
    checkbox.checked = data || false;
    checkbox.name = schema.path || schema.name;

    // 对于布尔值，我们不使用required属性，因为它会要求必须选中
    // 而是使用aria-required来标记UI - 优先使用thin.required
    const isRequired =
      schema.thin?.required !== undefined
        ? schema.thin.required
        : schema.parent &&
          schema.parent.required &&
          schema.parent.required.includes(schema.name);
    if (isRequired) {
      checkbox.setAttribute("aria-required", "true");
    }

    checkbox.onchange = (e) => {
      // 布尔值总是有效的，不需要验证
      checkbox.classList.remove("invalid");
      updateData(e.target.checked);
    };

    wrapper.appendChild(checkbox);
    return wrapper;
  }

  /**
   * 创建文本区域
   * @param {Object} schema - Schema定义
   * @param {*} data - 数据值
   * @param {Function} updateData - 数据更新函数
   * @returns {HTMLElement} 输入元素
   */
  static createTextarea(schema, data, updateData) {
    const textarea = document.createElement("textarea");
    textarea.value = data || "";
    textarea.name = schema.path || schema.name;

    // 添加必填验证 - 优先使用thin.required
    const isRequired =
      schema.thin?.required !== undefined
        ? schema.thin.required
        : schema.parent &&
          schema.parent.required &&
          schema.parent.required.includes(schema.name);
    if (isRequired) {
      textarea.required = true;
      textarea.setAttribute("aria-required", "true");
    }

    if (schema.thin?.rows) textarea.rows = schema.thin.rows;

    textarea.onchange = (e) => {
      if (textarea.checkValidity()) {
        textarea.classList.remove("invalid");
        updateData(e.target.value);
      } else {
        textarea.classList.add("invalid");
      }
    };

    return textarea;
  }

  /**
   * 创建特殊输入类型
   * @param {Object} schema - Schema定义
   * @param {*} data - 数据值
   * @param {Function} updateData - 数据更新函数
   * @returns {HTMLElement} 输入元素
   */
  static createSpecialInput(schema, data, updateData) {
    const input = document.createElement("input");
    const type = schema.thin?.type;
    input.name = schema.path || schema.name;

    switch (type) {
      case "date":
      case "datetime":
      case "email":
      case "tel":
      case "url":
      case "password":
      case "time":
        input.type = type === "datetime" ? "datetime-local" : type;
        input.value = data || "";
        break;
      case "color":
        input.type = "color";
        input.value = data || "#000000";
        break;
      default:
        input.type = "text";
        input.value = data || "";
    }

    // 添加必填验证 - 优先使用thin.required
    const isRequired =
      schema.thin?.required !== undefined
        ? schema.thin.required
        : schema.parent &&
          schema.parent.required &&
          schema.parent.required.includes(schema.name);
    if (isRequired) {
      input.required = true;
      input.setAttribute("aria-required", "true");
    }

    input.onchange = (e) => {
      let value = e.target.value;
      if (input.type === "number") value = Number(value);
      else if (input.type === "checkbox") value = e.target.checked;

      if (input.checkValidity()) {
        input.classList.remove("invalid");
        updateData(value);
      } else {
        input.classList.add("invalid");
      }
    };

    return input;
  }
}
